package library.Logs;
 
import java.util.*;

import javax.swing.JTextArea;

import org.apache.log4j.*;
import org.apache.log4j.spi.*;

import library.RemoteControl.*;

/**
 * Class_TextAreaAppender implements the redirection of the logs to à JTextArea
 * object
 * @author JNC
 */
public class TextAreaAppender extends AppenderSkeleton {

    /**
     * The delay in ms to wait till the auto scrool down be enabled again
     */
    static final long _TIMER_DELAY = 30000; // ms
    
    /**
     * The log4j logger.
     */
     private static final Logger _logger = Logger.getLogger(TextAreaAppender.class);
     
    /**
     * The JTextArea where logs will be directed to.
     */
     private JTextArea _textArea;
    
    /**
     * Indicates whether the auto scroll down capability is enabled
     */
    private boolean _autoScrollDown;
    
    /**
     * A reference to the remote control.<br/>
     */
    private RemoteControlInterface _remoteControl;
    
    /**
     * The timer to enable automatically the auto scroll down
     */
    private Timer _timer;
    
  
    
    /**
     * Constructor. <br/>
     * Seems not to be called : initialization of _autoScrollDown attribute is made
     * in the setParameters method. <br/>
     */
    public TextAreaAppender() {
    }
    
    /**
     * Finds the relevant Appender and assigns the JTextArea and the remote control. <br/>
     * In addition, enables auto scrolling.<br/>
     * This method must be called after the JTextArea and the remote control have been created. <br/>
     * This method must also be called prior any call to append. <br/>
     * The JTextArea is the zone to log all messages. <br/>
     * The remote control is the area where all messages are logged. <br/>
     * @param myTextArea
     * The text area where all messages are logged.<br/>
     */
    @SuppressWarnings("unchecked")
	public static void setParameters(JTextArea myTextArea, RemoteControlInterface myRemoteControl) {

        // gets the root logger
        Logger rootLogger = Logger.getRootLogger();
        
        if (rootLogger == null) {
            System.err.println("Logger.getRootLogger() return null");
        } else {
            
            // gets all appenders
            Enumeration<Appender> enumAppenders = rootLogger.getAllAppenders();
            if (enumAppenders == null) {
                System.err.println("getAllAppenders() return null");
            } else {
                
                // loops all appenders
                while (enumAppenders.hasMoreElements()) {
                    Appender app = (Appender)enumAppenders.nextElement();
                    
                    // finds the relevant appender
                    if (app instanceof TextAreaAppender) {
                        ((TextAreaAppender)app).setTextAreaAttribute(myTextArea);
                        ((TextAreaAppender)app).setRemoteControlAttribute(myRemoteControl);
                        ((TextAreaAppender)app).setAutoScrollAttribute(true);
                        ((TextAreaAppender)app).setTimerAttribute(null);
                    } // if app instanceof TextAreaAppender
                } // while
            } // if enumAppenders != null
        } // if rootLoger != null
    }
    
    /**
     * Sets the remote control atttribute, and registers the Class_TextAreaAppender
     * in the remote control
     * @param myRemoteControl
     * The remote control to assign
     */
    private void setRemoteControlAttribute(RemoteControlInterface myRemoteControl) {
        _remoteControl = myRemoteControl;
        
        try {
            _remoteControl.register(this);
        } catch (UnknownClassException exception) {
            System.err.println("Unable to register the Class_textAreaAppender");
        } // catch
    }

    /**
     * Sets the text area attribute
     * @param myTextArea
     * The JTextArea to set
     */
    private void setTextAreaAttribute(JTextArea myTextArea) {
        _textArea = myTextArea;
    }
    
    /**
     * Indicates whether a layout is required.
     * @return
     * always returns true.
     */
    public boolean requiresLayout() {
        return true;
    }
    
    /**
     * Appends an event to the JTextArea. <br/>
     * Mandatory API when defining a new appender.<br/>
     * This method will not proceed correctly if setTextArea was not called
     * before.
     * @param myEvent
     * The event to log
     */
    protected void append(LoggingEvent myEvent) {
        Layout layoutToApply = null;
        String stringToLog = null;
        
        // format the string if possible
        layoutToApply = getLayout();
        if (layoutToApply == null) {
            System.out.print("TextAreaAppender : did not found any layout");
        } else { // if layout == null
            stringToLog = layoutToApply.format(myEvent);
        }
        
        // log the message if possible
        if (_textArea != null) {
//            System.err.print("TextAreaAppender not initialized - msg was : " + stringToLog);
//        } else { // if _textArea == null
            _textArea.append(stringToLog);
            
            // auto scroll down scroll to the end of the JTextArea
            if (_autoScrollDown) {
                _textArea.setCaretPosition(_textArea.getDocument().getLength());
            } // if _autoScrollDown
        } // if _textArea != null
    } 
    
    /**
     * Terminates the objet.<br/>
     * Mandatory API when defining a new appender.<br/>
     */
    public void close() {
        _textArea = null;
        _remoteControl=null;
    }
    
    /**
     * Disables temporary the auto scroll down capability, and starts a timer
     * to enable again the auto scroll down capability. <br/>
     * @param myAutoScrollToEnable
     * true to enable scrrol down
     * false to disable scroll down
     */
    public void disableAutoScrollDownTemporary() {
        // if disabling again auto scroll down, reinit the timer
        if (!_autoScrollDown) {
            _logger.debug("Disabling the timer");
            _timer.cancel();
            setTimerAttribute(null);
        }
        
        // Starts a timer
        _timer=new Timer();
        _logger.debug("enabling the timer");
        _timer.schedule(new TimerTask() {
            public void run() {
                _logger.debug("timer has expired");
                
                setAutoScrollAttribute(true);
                
                // goes to the end of the text area
                _textArea.setCaretPosition(_textArea.getDocument().getLength());
                
                // reinit the border of the text area
                _logger.debug("Change border to NON transient");
                _remoteControl.changeBorderToTransient(false);
            }
        }, _TIMER_DELAY);
            
        // modify the border of the scroll area
        _logger.debug("Change border to transient");
        _remoteControl.changeBorderToTransient(true);
        
        // sets the auto scroll down attribute
        setAutoScrollAttribute(false);
    }

    /**
     * sets the auto scroll attribute
     * @param myAutoScroll
     * value of the _autoScrollDown attribute
     */
    private void setAutoScrollAttribute(boolean myAutoScroll) {
        _autoScrollDown = myAutoScroll;
    }
    
    /**
     * Sets the timer attribute
     * @param myTimer
     * The time to set
     */
    private void setTimerAttribute(Timer myTimer) {
        _timer = myTimer;
    }
}
